package cn.b.sky.mes.cm.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import cn.b.sky.mes.cm.constants.CmConstant;
import cn.b.sky.mes.cm.dao.ProcessAttachmentDao;
import cn.b.sky.mes.cm.dao.ProcessCapacityDao;
import cn.b.sky.mes.cm.dao.ProcessComponentDao;
import cn.b.sky.mes.cm.dao.ProcessInspectPictureDao;
import cn.b.sky.mes.cm.dao.ProcessModelDao;
import cn.b.sky.mes.cm.dao.ProcessOperationDao;
import cn.b.sky.mes.cm.enums.OperationType;
import cn.b.sky.mes.cm.model.ProcessAttachment;
import cn.b.sky.mes.cm.model.ProcessCapacity;
import cn.b.sky.mes.cm.model.ProcessComponent;
import cn.b.sky.mes.cm.model.ProcessInspectPicture;
import cn.b.sky.mes.cm.model.ProcessModel;
import cn.b.sky.mes.cm.model.ProcessOperation;
import cn.b.sky.mes.cm.model.ProcessOperationCapacity;
import cn.b.sky.mes.cm.model.condition.ProcessCondition;
import cn.b.sky.mes.cm.service.ProcessService;
import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.common.model.Page;
import cn.b.sky.common.utils.FTPUtils;
import cn.b.sky.common.utils.SkyFileUtils;
import cn.b.sky.common.utils.SpringBeanUtil;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.user.model.Attachment;
import cn.b.sky.user.service.AttachmentService;

@Service("processService")
public class ProcessSerivceImpl implements ProcessService {
  private static final Logger LOGGER = LoggerFactory.getLogger(ProcessSerivceImpl.class);

  @Autowired
  private ProcessModelDao processModelDao;

  @Autowired
  private ProcessOperationDao processOperationDao;

  @Autowired
  private ProcessComponentDao processComponentDao;

  @Autowired
  private ProcessAttachmentDao processAttachmentDao;

  @Autowired
  private ProcessCapacityDao processCapacityDao;

  @Autowired
  private ProcessInspectPictureDao processInspectPictureDao;

  @Resource
  AttachmentService attachmentService;

  @Override
  public Page getProcessPageByCondition(ProcessCondition condition) {
    if (condition == null) {
      condition = new ProcessCondition();
    }
    //默认按照创建时间排序
    if (StringUtils.isBlank(condition.getOrderField())) {
      condition.setOrderField("CreateDateTime");
    }
    List<ProcessModel> pms = processModelDao.selectProcessPageByCondition(condition);
    int count = processModelDao.selectProcessCountByCondition(condition);
    condition.setData(pms);
    condition.setTotalCount(count);
    return condition;
  }

  @Override
  public void saveProcess(ProcessModel process, String processOprationIds) {
    if (process == null) {
      return;
    }
    processModelDao.insertProcess(process);
    List<ProcessOperation> ops = process.getOperations();
    if (ops != null && ops.size() > 0) {
      this.batchSaveProcessOperation(ops, process);
    }
    if (!StringUtils.isBlank(processOprationIds)) {
      for (String popId : processOprationIds.split(",")) {
        if (StringUtils.isBlank(popId)) {
          continue;
        }
        //此处修改保持原数据
        ProcessOperation processOperation = this.getProcessOperationById(Integer.parseInt(popId));
        processOperation.setProcessCode(process.getProcessCode());
        processOperation.setProcessRev(process.getProcessRev());
        processOperationDao.updateProcessOperation(processOperation);
      }

    }
  }

  @Override
  public void modifyProcess(ProcessModel process, String processOprationAddIds, String processOprationDelIds) {
    if (process != null) {
      processModelDao.updateProcess(process);
    }
    if (!StringUtils.isBlank(processOprationAddIds)) {
      for (String popId : processOprationAddIds.split(",")) {
        if (StringUtils.isBlank(popId)) {
          continue;
        }
        //此处修改保持原数据
        ProcessOperation processOperation = this.getProcessOperationById(Integer.parseInt(popId));
        processOperation.setProcessCode(process.getProcessCode());
        processOperation.setProcessRev(process.getProcessRev());
        processOperationDao.updateProcessOperation(processOperation);
      }
    }
    if (!StringUtils.isBlank(processOprationDelIds)) {
      for (String popId : processOprationDelIds.split(",")) {
        if (!StringUtils.isBlank(popId)) {
          this.deleteProcessOperationById(Integer.parseInt(popId));
        }
      }

    }
  }

  @Override
  public void deleteProcess(ProcessModel process) {
    if (process != null && StringUtils.isNotBlank(process.getSiteCode())
        && StringUtils.isNotBlank(process.getProcessCode()) && StringUtils.isNotBlank(process.getProcessRev())) {
      this.deleteProcessOperationByProcess(process.getSiteCode(), process.getProcessCode(), process.getProcessRev());
      processModelDao.deleteProcess(process.getSiteCode(), process.getProcessCode(), process.getProcessRev());
    }
  }

  @Override
  public ProcessModel getProcessBySCodeAndPCode(String siteCode, String processCode, String processrev) {
    if (StringUtils.isNotBlank(siteCode) && StringUtils.isNotBlank(processCode) && StringUtils.isNotBlank(processrev)) {
      return processModelDao.selectProcessByPK(siteCode, processCode, processrev);
    }

    return null;
  }

  @Override
  public List<ProcessOperation> getProcessOperationByProcessCode(String siteCode, String processCode,
      String processrev) {
    if (StringUtils.isNotBlank(siteCode) && StringUtils.isNotBlank(processCode) && StringUtils.isNotBlank(processrev)) {
      return processOperationDao.selectProcessOperationByProcess(siteCode, processCode, processrev);
    }
    return new ArrayList<ProcessOperation>();
  }

  @Override
  public ProcessModel getProcessBySCodeAndEffectiveDate(String siteCode, String processCode, Date effectiveDate) {

    if (StringUtils.isNotBlank(siteCode) && StringUtils.isNotBlank(processCode) && effectiveDate != null) {
      return processModelDao.selectProcessByCodeAndEffectiveDate(siteCode, processCode, effectiveDate);
    }
    return null;
  }

  @Override
  public List<ProcessComponent> getProcessComponentByProcessOperation(Integer processOperationId) {
    if (processOperationId != null) {
      return processComponentDao.selectProcessComponentByProcessOperationId(processOperationId);
    }
    return new ArrayList<ProcessComponent>();
  }

  @Override
  public List<ProcessAttachment> getProcessAttachmentByProcessOperation(Integer processOperationId) {
    if (processOperationId != null) {
      return processAttachmentDao.selectProcessAttachmentByProcessOperationId(processOperationId);
    }
    return new ArrayList<ProcessAttachment>();
  }

  @Override
  public List<ProcessInspectPicture> getProcessInspectPictureByProcessOperation(Integer processOperationId) {
    if (processOperationId != null) {
      return processInspectPictureDao.selectProcessInspectPictureByProcessOperationId(processOperationId);
    }
    return new ArrayList<ProcessInspectPicture>();
  }

  @Override
  public void batchSaveProcessOperation(List<ProcessOperation> ops, ProcessModel process) {
    if (ops == null || ops.size() <= 0) {
      return;
    }
    if (process == null) {
      return;
    }
    if (StringUtils.isNotBlank(process.getSiteCode()) && StringUtils.isNotBlank(process.getProcessCode())
        && StringUtils.isNotBlank(process.getProcessRev())) {
      for (ProcessOperation op : ops) {
        op.setProcessCode(process.getProcessCode());
        op.setSiteCode(process.getSiteCode());
        op.setProcessRev(process.getProcessRev());
        this.processOperationDao.insertProcessOperation(op);
        List<ProcessComponent> components = op.getComponent();
        List<ProcessAttachment> attachments = op.getAttachment();
        batchSaveProcessComponent(components, op.getId());
        batchSaveProcessAttachment(attachments, op.getId());
      }
    }

  }

  @Override
  public void deleteProcessOperationByProcess(String siteCode, String processCode, String processrev) {
    if (!StringUtils.isBlank(siteCode) && !StringUtils.isBlank(processCode) && !StringUtils.isBlank(processrev)) {
      List<ProcessOperation> pops = this.getProcessOperationByProcessCode(siteCode, processCode, processrev);
      for (ProcessOperation pop : pops) {
        if (pop != null) {
          this.deleteProcessOperationById(pop.getId());
        }
      }
    }

  }

  @Override
  public void batchSaveProcessComponent(List<ProcessComponent> components, Integer popId) {
    if (components != null && components.size() > 0 && popId != null) {
      for (ProcessComponent component : components) {
        if (component != null && !StringUtils.isBlank(component.getComponentCode())) {
          component.setProcessOperationID(popId);
          processComponentDao.insertProcessComponent(component);
        }
      }
    }

  }

  @Override
  public void batchSaveProcessAttachment(List<ProcessAttachment> attachments, Integer popId) {
    if (attachments != null && attachments.size() > 0 && popId != null) {
      for (ProcessAttachment attachment : attachments) {
        if (attachment != null && !StringUtils.isBlank(attachment.getAttachmentCode())) {
          attachment.setProcessOperationID(popId);
          processAttachmentDao.insertProcessAttachment(attachment);
        }
      }
    }
  }

  @Override
  public void batchSaveProcessInspectPicture(List<ProcessInspectPicture> pictures, Integer popId) {
    if (pictures != null && pictures.size() > 0 && popId != null) {
      for (ProcessInspectPicture attachment : pictures) {
        if (attachment != null && !StringUtils.isBlank(attachment.getAttachmentCode())) {
          attachment.setProcessOperationID(popId);
          processInspectPictureDao.insertProcessInspectPicture(attachment);
        }
      }
    }
  }

  @Override
  public void deleteProcessComponentByProcessOperation(Integer processOperationId, String componentCode) {
    if (processOperationId != null && !StringUtils.isBlank(componentCode)) {
      processComponentDao.deleteProcessComponentByPk(processOperationId, componentCode);
    }

  }

  @Override
  public void deleteProcessAttachmentById(Long id) {
    if (id != null) {
      ProcessAttachment attachment = processAttachmentDao.selectProcessAttachmentById(id);
      FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
      ftpUtils.deleteFile(attachment.getSavePath());
      processAttachmentDao.deleteProcessAttachmentById(id);
    }

  }

  @Override
  public void deleteProcessInspectPicById(Long id) {
    if (null != id) {
      ProcessInspectPicture pic = processInspectPictureDao.selectProcessInspectPictureById(id);
      FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
      ftpUtils.deleteFile(pic.getSavePath());
      processInspectPictureDao.deleteProcessInspectPictureById(id);
    }

  }

  @Override
  public void saveOrUpdateProcessOperation(ProcessOperation pop) {
    if (pop != null && StringUtils.isNotBlank(pop.getSiteCode())) {
      if (pop.getId() == null) {
        this.processOperationDao.insertProcessOperation(pop);
      } else {
        this.processOperationDao.updateProcessOperation(pop);
        this.processAttachmentDao.deleteProcessAttachmentByProcessOperationId(pop.getId());
        this.processCapacityDao.deleteProcessCapacityByProcessOperationId(pop.getId());
        if (OperationType.QUALITY.getValue().equals(pop.getOperationTypeEcode())) {
          this.processInspectPictureDao.deleteProcessInspectPictureByProcessOperationId(pop.getId());
        } else if (OperationType.PRODUCTION.getValue().equals(pop.getOperationTypeEcode())) {
          this.processComponentDao.deleteProcessComponentByProcessOperationId(pop.getId());
        }
      }
      this.batchSaveProcessAttachment(pop.getAttachment(), pop.getId());
      this.batchSaveProcessCapacity(pop.getCapacity(), pop.getId(), pop.getSiteCode());
      if (OperationType.QUALITY.getValue().equals(pop.getOperationTypeEcode())) {
        this.batchSaveProcessInspectPicture(pop.getPicture(), pop.getId());
      } else if (OperationType.PRODUCTION.getValue().equals(pop.getOperationTypeEcode())) {
        this.batchSaveProcessComponent(pop.getComponent(), pop.getId());
      }
    }

  }

  @Override
  public void deleteProcessOperationById(Integer id) {
    if (id != null) {
      this.processAttachmentDao.deleteProcessAttachmentByProcessOperationId(id);
      this.processCapacityDao.deleteProcessCapacityByProcessOperationId(id);
      this.processComponentDao.deleteProcessComponentByProcessOperationId(id);
      this.processInspectPictureDao.deleteProcessInspectPictureByProcessOperationId(id);
      this.processOperationDao.deleteProcessOperationById(id);
    }
  }

  @Override
  public void saveProcessComponent(ProcessComponent component) {
    if (component != null && component.getProcessOperationID() != null) {
      //已存在就修改，不然就新增
      ProcessComponent cop = processComponentDao.selectProcessComponentByPk(component.getProcessOperationID(),
          component.getComponentCode());
      if (cop != null && cop.getProcessOperationID() != null) {
        this.processComponentDao.updateProcessComponent(component);
      } else {
        this.processComponentDao.insertProcessComponent(component);
      }
    }

  }

  @Override
  public void saveProcessAttachment(ProcessAttachment processAttachment, MultipartFile file) {
    if (processAttachment != null && !StringUtils.isBlank(processAttachment.getSiteCode())) {
      String filePath = SkyFileUtils.buildFilePath("processOperation");
      String fileName = file.getOriginalFilename();
      String md5 = "";
      try {
        md5 = SkyFileUtils.getMD5String(file.getBytes());
      } catch (IOException e) {
        LOGGER.error("{}", e);
      }
      Attachment att = attachmentService.selectAttachmentByHashCode(processAttachment.getSiteCode(), md5);
      String saveName = UUID.randomUUID().toString();
      //MD5校验，映射文件
      if (att != null) {
        att.setRefCount(att.getRefCount() + 1);
        attachmentService.updateAttachmentRefCount(att);
        processAttachment.setAttachmentCode(att.getAttachmentCode());
        processAttachment.setFileSize(att.getFileSize());
        processAttachment.setFileName(fileName);
        processAttachment.setSavePath(att.getSavePath());
      } else {
        String newFileName = SkyFileUtils.renameFileName(fileName, saveName);
        FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
        String savePath = ftpUtils.uploadMultipartFiles(file, filePath, newFileName);
        Long size = file.getSize();
        processAttachment.setAttachmentCode(saveName);
        processAttachment.setFileSize(size);
        processAttachment.setSavePath(savePath);
        processAttachment.setFileName(fileName);
        att = new Attachment(saveName, savePath, fileName, size, md5, 1);
        att.setSiteCode(processAttachment.getSiteCode());
        attachmentService.insertAttachment(att);
      }

      //this.processAttachmentDao.insertProcessAttachment(processAttachment);先不入库
    }
  }

  @Override
  public void saveProcessInspectPicture(Attachment attachment, MultipartFile file) {
    if (attachment != null && !StringUtils.isBlank(attachment.getSiteCode())) {
      String filePath = SkyFileUtils.buildFilePath("processOperation");
      String fileName = file.getOriginalFilename();
      String md5 = "";
      try {
        md5 = SkyFileUtils.getMD5String(file.getBytes());
      } catch (IOException e) {
        LOGGER.error("{}", e);
      }
      Attachment att = attachmentService.selectAttachmentByHashCode(attachment.getSiteCode(), md5);
      //MD5校验，映射文件
      if (att != null) {
        att.setRefCount(att.getRefCount() + 1);
        attachmentService.updateAttachmentRefCount(att);
        attachment.setAttachmentCode(att.getAttachmentCode());
        attachment.setFileSize(att.getFileSize());
        attachment.setFileName(fileName);
        attachment.setSavePath(att.getSavePath());
      } else {
        String attachmentCode = UUID.randomUUID().toString();
        String newFileName = SkyFileUtils.renameFileName(fileName, attachmentCode);
        FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
        String savePath = ftpUtils.uploadMultipartFiles(file, filePath, newFileName);
        Long size = file.getSize();
        attachment.setAttachmentCode(attachmentCode);
        attachment.setFileSize(size);
        attachment.setSavePath(savePath);
        attachment.setFileName(fileName);
        att = new Attachment(attachmentCode, savePath, fileName, size, md5, 1);
        att.setSiteCode(attachment.getSiteCode());
        attachmentService.insertAttachment(att);
      }
    } else {
      throw ImeException.newException(SystemConstant.PARAMETERNULL);
    }

  }

  @Override
  public ProcessAttachment getProcessAttachmentById(Long id) {
    if (null != id) {
      return processAttachmentDao.selectProcessAttachmentById(id);
    }
    return null;
  }

  @Override
  public ProcessInspectPicture getProcessInspectPictureByPk(Long id) {
    if (null != id) {
      return processInspectPictureDao.selectProcessInspectPictureById(id);
    }
    return null;
  }

  @Override
  public ProcessOperation getProcessOperationById(Integer id) {
    if (null != id) {
      return processOperationDao.selectProcessOperationById(id);
    }
    return null;
  }

  @Override
  public boolean checkProcessIsUsedByMaterial(String processCode, String siteCode, String materialCode) {
    if (StringUtils.isBlank(processCode) || StringUtils.isBlank(siteCode)) {
      return false;
    }
    int count = processModelDao.selectMaterialByProcessCodeAndMCode(processCode, siteCode, materialCode);

    return count > 0 ? true : false;
  }

  @Override
  public List<ProcessOperation> copyProcessOperationByProcessPk(String siteCode, String processCode,
      String processrev) {
    if (!StringUtils.isBlank(siteCode) && !StringUtils.isBlank(processCode) && !StringUtils.isBlank(processrev)) {
      List<ProcessOperation> pops = this.getProcessOperationByProcessCode(siteCode, processCode, processrev);
      if (pops != null) {
        for (ProcessOperation p : pops) {
          p.setProcessCode(CmConstant.PROCESSCODE_TEMP);
          p.setProcessRev(CmConstant.PROCESSREV_TEMP);
          List<ProcessComponent> component = null;
          List<ProcessAttachment> attachment = null;
          List<ProcessInspectPicture> pictures = null;
          List<ProcessCapacity> capacities = null;
          attachment = this.getProcessAttachmentByProcessOperation(p.getId());
          capacities = this.getProcessCapacityByProcessOperation(p.getId());
          if (OperationType.PRODUCTION.getValue().equals(p.getOperationTypeEcode())) {
            component = this.getProcessComponentByProcessOperation(p.getId());
          } else if (OperationType.QUALITY.getValue().equals(p.getOperationTypeEcode())) {
            pictures = this.getProcessInspectPictureByProcessOperation(p.getId());
          }
          p.setId(null);
          //保存
          this.saveOrUpdateProcessOperation(p);
          //复制component
          this.batchSaveProcessComponent(component, p.getId());
          this.batchSaveProcessAttachment(attachment, p.getId());
          this.batchSaveProcessInspectPicture(pictures, p.getId());
          this.batchSaveProcessCapacity(capacities, p.getId(), p.getSiteCode());
        }
      }
      return pops;
    }
    return new ArrayList<ProcessOperation>();
  }

  @Override
  public void deleteTempProcessOperation(ProcessOperation pop) {
    if (pop != null) {
      List<ProcessOperation> pops = processOperationDao.getTempProcessOperation(pop);
      if (pops != null && pops.size() > 0) {
        for (ProcessOperation p : pops) {
          processComponentDao.deleteProcessComponentByProcessOperationId(p.getId());
          processAttachmentDao.deleteProcessAttachmentByProcessOperationId(p.getId());
          processInspectPictureDao.deleteProcessInspectPictureByProcessOperationId(p.getId());
          processCapacityDao.deleteProcessCapacityByProcessOperationId(p.getId());
        }
        processOperationDao.deleteTempProcessOperation(pop);
      }
    }
  }

  @Override
  public ProcessModel checkTempProcessByPk(String siteCode, String processcode, String processrev) {
    ProcessModel temp = this.getProcessBySCodeAndPCode(siteCode, processcode, processrev);
    if (temp == null) {
      temp = new ProcessModel();
      temp.setProcessCode(processcode);
      temp.setSiteCode(siteCode);
      temp.setProcessRev(processrev);
      temp.setEffectiveDate(new Date());
      temp.setLockFlag(0);
      temp.setCreateDateTime(new Date());
      temp.setCreateUser("SYSTEM");
      temp.setModifyDateTime(new Date());
      temp.setModifyUser("SYSTEM");
      processModelDao.insertProcess(temp);
    }
    return temp;
  }

  @Override
  public Page getNoVersionProcessPageByCondition(ProcessCondition condition) {
    if (condition == null) {
      condition = new ProcessCondition();
    }
    //默认按照创建时间排序
    if (StringUtils.isBlank(condition.getOrderField())) {
      condition.setOrderField("CreateDateTime");
    }
    condition.setCurrentTime(new Date());
    List<ProcessModel> pms = processModelDao.selectNoVersionProcessPageByCondition(condition);
    int count = processModelDao.selectNoVersionProcessCountByCondition(condition);
    condition.setData(pms);
    condition.setTotalCount(count);
    return condition;
  }

  @Override
  public List<ProcessOperation> selectProcessOperationsForDefectGraph(String siteCode, String processCode,
      String processrev, OperationType operationTypeEcode, Integer graphCollectFlag) {
    return processOperationDao.selectProcessOperationForDefectGraph(siteCode, processCode, processrev,
        operationTypeEcode, graphCollectFlag);
  }

  @Override
  public ProcessInspectPicture selectProcessInspectPictureByCode(String attachmentcode) {
    if (!StringUtils.isEmpty(attachmentcode)) {
      return processInspectPictureDao.selectProcessInspectPictureByCode(attachmentcode);
    }
    return null;
  }

  @Override
  public void batchSaveProcessCapacity(List<ProcessCapacity> capacities, Integer popId, String siteCode) {
    if (capacities != null && capacities.size() > 0 && popId != null) {
      for (ProcessCapacity capacity : capacities) {
        if (capacity != null && !StringUtils.isBlank(capacity.getWorkUnitCode())) {
          capacity.setProcessOperationID(popId);
          capacity.setSiteCode(siteCode);
          capacity.setCreateDateTime(new Date());
          capacity.setCreateUser(SecurityContextUtil.getCurrentUserName());
          capacity.setModifyDateTime(new Date());
          capacity.setModifyUser(SecurityContextUtil.getCurrentUserName());
          processCapacityDao.insertProcessCapacity(capacity);
        }
      }
    }
  }

  @Override
  public List<ProcessCapacity> getProcessCapacityByProcessOperation(Integer processOperationId) {
    if (processOperationId != null) {
      return processCapacityDao.selectProcessCapacityByProcessOperationId(processOperationId);
    }
    return new ArrayList<ProcessCapacity>();
  }

  @Override
  public List<ProcessOperationCapacity> getStandardCapacity(String siteCode, Integer[] processOperationIds) {
    return processOperationDao.getStandardCapacity(siteCode, processOperationIds);
  }

  @Override
  public List<ProcessOperation> getConfirmationProcessOperation(String siteCode, String productionOrderNum) {
    return processOperationDao.selectConfirmationProcessOperation(siteCode, productionOrderNum,
        OperationType.PRODUCTION.getValue());
  }

  @Override
  public List<ProcessOperation> selectProcessOperationByProcess(String siteCode, String processCode,
      String processRev) {
    return processOperationDao.selectProcessOperationByProcess(siteCode, processCode, processRev);
  }

}
